package at.ac.univie.zsu.aguataplan.ui;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import uk.co.caprica.vlcj.binding.internal.libvlc_media_t;
import uk.co.caprica.vlcj.player.MediaPlayer;
import uk.co.caprica.vlcj.player.MediaPlayerEventListener;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import at.ac.univie.zsu.aguataplan.property.GeneralProperties;
import at.ac.univie.zsu.aguataplan.property.SystemProperties;
import at.ac.univie.zsu.aguataplan.property.UIProperties;
import at.ac.univie.zsu.aguataplan.util.Constants;
import at.ac.univie.zsu.aguataplan.util.Monitor;
import at.ac.univie.zsu.aguataplan.util.TimeUtil;

import com.sun.jna.NativeLibrary;

/**
 * @author gerry
 * 
 */
public class VideoPlayerPanel extends JPanel implements UIConstants, Constants, IVideoPlayer {
	private static final long serialVersionUID = 5158099692857266972L;

	private VideoControlPanel controlPanel;
	private UIProperties guiProperties;
	private SystemProperties systemProperties;

	private EmbeddedMediaPlayer mpfs;
	private Canvas cf;
	private JPanel pf;
	private JFrame fs;

	private Canvas vs;
	private EmbeddedMediaPlayer mp;
	private MediaPlayerFactory factory;
	private float playbackSpeed;

	private IForegroundChange iModalChange;

	private String s;

	private int volume;

	// ----------------------------------------------------
	// CONSTRUCTOR
	// ----------------------------------------------------

	public VideoPlayerPanel(GeneralProperties generalProperties, IForegroundChange iModalChange, String file) {
		this.guiProperties = generalProperties.getUiProperties();
		this.systemProperties = generalProperties.getSystemProperties();
		this.iModalChange = iModalChange;

		NativeLibrary.addSearchPath("libvlc", systemProperties.getDirVlc());

		this.setLayout(new BorderLayout());

		vs = new Canvas();

		this.playbackSpeed = 1f;

		String[] vlcArgs = { "--no-video-title-show", "--clock-jitter=0" };
		factory = new MediaPlayerFactory(vlcArgs);

		this.setPreferredSize(new Dimension(PANEL_VIDEO_X, PANEL_VIDEO_Y));

		controlPanel = new VideoControlPanel(generalProperties, this);

		this.add(vs, BorderLayout.CENTER);
		this.add(controlPanel, BorderLayout.SOUTH);

		this.setVisible(true);

		mp = factory.newEmbeddedMediaPlayer();
		mp.setVideoSurface(factory.newVideoSurface(vs));

		s = file;

		mp.prepareMedia(s, "");
		this.volume = guiProperties.getVolumeStart();
		mp.setVolume(this.volume);

		mp.addMediaPlayerEventListener(new MediaPlayerEventListener() {

			@Override
			public void titleChanged(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void timeChanged(MediaPlayer arg0, long arg1) {
			}

			@Override
			public void subItemPlayed(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void subItemFinished(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void stopped(MediaPlayer arg0) {
			}

			@Override
			public void snapshotTaken(MediaPlayer arg0, String arg1) {
			}

			@Override
			public void seekableChanged(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void positionChanged(MediaPlayer arg0, final float arg1) {
				controlPanel.changePositionSlider(arg1);
			}

			@Override
			public void playing(MediaPlayer arg0) {
			}

			@Override
			public void paused(MediaPlayer arg0) {
			}

			@Override
			public void pausableChanged(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void opening(MediaPlayer arg0) {
			}

			@Override
			public void newMedia(MediaPlayer arg0) {
			}

			@Override
			public void mediaSubItemAdded(MediaPlayer arg0, libvlc_media_t arg1) {
			}

			@Override
			public void mediaStateChanged(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void mediaParsedChanged(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void mediaMetaChanged(MediaPlayer arg0, int arg1) {
			}

			@Override
			public void mediaFreed(MediaPlayer arg0) {
			}

			@Override
			public void mediaDurationChanged(MediaPlayer arg0, long arg1) {
			}

			@Override
			public void mediaChanged(MediaPlayer arg0) {
			}

			@Override
			public void lengthChanged(MediaPlayer arg0, long arg1) {
			}

			@Override
			public void forward(MediaPlayer arg0) {
			}

			@Override
			public void finished(MediaPlayer arg0) {
			}

			@Override
			public void error(MediaPlayer arg0) {
			}

			@Override
			public void endOfSubItems(MediaPlayer arg0) {
			}

			@Override
			public void buffering(MediaPlayer arg0) {
			}

			@Override
			public void backward(MediaPlayer arg0) {
			}
		});

	}

	// ----------------------------------------------------
	// METHODS
	// ----------------------------------------------------

	public void init() {
		mp.start();
		mp.pause();
	}

	public void quit() {
		if (mp != null) {
			mp.stop();
			mp = null;
		}
		if (mpfs != null) {
			mpfs.stop();
			mpfs = null;
		}
		// mp.release();
		// mpfs.release();
		// factory.release();

	}

	public boolean isPlaying() {
		return mp.isPlaying();
	}

	/**
	 * change position in video and on slider
	 * 
	 * @param position
	 */
	public void setPositionFloat(float position) {
		mp.setPosition(position);
		controlPanel.changePositionSlider(position);
	}

	/**
	 * get position of video in long
	 * 
	 * @return
	 */
	public long getTimeLong() {
		return mp.getTime();
	}

	// ----------------------------------------------------
	// IVideoPlayer INTERFACE
	// ----------------------------------------------------
	@Override
	public void stop() {
		if (mp == null) {
			return;
		}

		this.playbackSpeed = 1f;
		this.mp.setRate(playbackSpeed);
		mp.pause();
		mp.setPosition(0);
		mp.start();
	}

	@Override
	public void play() {
		if (mp == null) {
			return;
		}

		this.playbackSpeed = 1f;
		this.mp.setRate(playbackSpeed);
		this.mp.play();
	}

	@Override
	public void pause() {
		if (mp == null) {
			return;
		}
		if (mp.isPlaying()) {
			mp.pause();
		}
	}

	@Override
	public void increaseSpeed() {
		if (mp == null) {
			return;
		}
		// check if maximum is reached
		if (this.playbackSpeed >= guiProperties.getIncreaseSpeedMax()) {
			return;
		}
		this.playbackSpeed = this.playbackSpeed + guiProperties.getIncreaseSpeed();
		this.playbackSpeed = Math.round(this.playbackSpeed * 100f) / 100f;
		mp.setRate(this.playbackSpeed);
	}

	@Override
	public void decreaseSpeed() {
		if (mp == null) {
			return;
		}
		// check if maximum is reached
		if (this.playbackSpeed <= guiProperties.getDecreaseSpeedMax()) {
			return;
		}
		this.playbackSpeed = this.playbackSpeed - (float) guiProperties.getDecreaseSpeed();
		mp.setRate(this.playbackSpeed);
	}

	@Override
	public String getPlaybackSpeed() {
		return TimeUtil.formDouble(playbackSpeed);
	}

	@Override
	public String getPlaybackPosition() {
		if (mp != null) {
			return TimeUtil.millisToShortDHMS(mp.getTime());
		}
		return "0,0";
	}

	@Override
	public String getPlaybackPositionMaximum() {
		if (mp != null) {
			return TimeUtil.millisToShortDHMS(mp.getLength());

		}
		return TimeUtil.millisToShortDHMS(0);
	}

	@Override
	public void setVolume(int volume) {
		if (mp == null) {
			return;
		}
		this.volume = volume;
		mp.setVolume(this.volume);
	}

	@Override
	public void setPosition(int pos) {
		if (mp == null) {
			return;
		}

		if (mp.isSeekable()) {
			float d = (float) pos / POSITION_MAX_SLIDER;

			mp.setPosition(d);
		}

	}

	@Override
	public float getPositionFloat() {
		return mp.getPosition();
	}

	@Override
	public void fullscreen() {
		pause();
		mp.mute(true);
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				cf = new Canvas();
				cf.setBackground(Color.black);

				pf = new JPanel();
				pf.setLayout(new BorderLayout());
				pf.add(cf, BorderLayout.CENTER);

				mpfs = factory.newEmbeddedMediaPlayer();

				mpfs.setVideoSurface(factory.newVideoSurface(cf));

				fs = new JFrame();
				fs.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				fs.addKeyListener(new KeyListener() {

					public void keyTyped(KeyEvent e) {
					}

					public void keyReleased(KeyEvent e) {
					}

					public void keyPressed(KeyEvent e) {
						if (e.getKeyCode() == 27) {
							SwingUtilities.invokeLater(new Runnable() {

								public void run() {
									mp.setPosition(mpfs.getPosition());
									mpfs.mute(true);
									mpfs.pause();
									fs.setVisible(false);
									iModalChange.setInForeground(true);
									// VideoPlayerPanel.this.setVisible(true);
									// if (!mp.isPlaying()) {
									// mp.play();
									// }
									// play();
									mp.play();
									mp.setVolume(VideoPlayerPanel.this.volume);
								}
							});
						}
					}
				});

				fs.setBounds(Monitor.calcPosition(VideoPlayerPanel.this.getLocationOnScreen()));

				iModalChange.setInForeground(false);

				fs.setContentPane(pf);
				fs.setUndecorated(true);
				fs.setResizable(false);
				fs.setVisible(true);
				fs.toFront();

				// VideoPlayerPanel.this.setVisible(false);

				mpfs.prepareMedia(s, "");
				mpfs.play();
				mpfs.setVolume(VideoPlayerPanel.this.volume);
				mpfs.setPosition(mp.getPosition());

			}
		});
	}
}
